Skip to content

Conversation

@dungbik
Copy link
Contributor

@dungbik dungbik commented Jul 28, 2025

📝 변경 내용


✅ 체크리스트

  • 코드가 정상적으로 동작함
  • 테스트 코드 통과함
  • 문서(README 등)를 최신화함
  • 코드 스타일 가이드 준수

💬 기타 참고 사항

Summary by CodeRabbit

  • 신규 기능

    • 회원가입, 비밀번호 변경, 소셜 연동 조회 및 삭제 등 인증 관련 신규 API가 추가되었습니다.
    • 사용자 인증 정보(UserAuth) 및 역할(AccountRole), 상태(AccountStatus) 관리 기능이 도입되었습니다.
    • 소셜 연동 관리, 토큰 버전 관리, 회원 탈퇴 이벤트 리스너가 새롭게 추가되었습니다.
    • 인증 주체를 나타내는 AuthPrinciple 타입이 도입되어 JWT 토큰과 인증 흐름에 적용되었습니다.
  • 변경 사항

    • 사용자 정보(UserProfile)와 인증 정보(UserAuth)가 명확히 분리되어 관리됩니다.
    • 기존 사용자 관련 일부 엔드포인트 및 서비스가 인증 컨트롤러 및 서비스로 이전되었습니다.
    • JWT 토큰에 userId가 포함되고, 인증 주체 타입이 AuthPrinciple로 통합되었습니다.
    • 그룹, 사용자, 인증 관련 서비스 및 컨트롤러의 인증 주체 타입이 UserAuth에서 AuthPrinciple로 변경되었습니다.
    • 사용자 엔티티가 User에서 UserProfile로 변경되고, 비밀번호 및 토큰 버전 관련 필드가 제거되었습니다.
    • 기존 사용자 서비스에서 비밀번호 변경, 소셜 연동 관련 기능이 제거되고 인증 서비스로 이관되었습니다.
    • 일부 enum 명칭 및 상태 값이 수정되고, 불필요한 코드와 주석이 정리되었습니다.
  • 버그 수정

    • enum 구문 오류 수정 및 일부 명칭 정정.
  • 테스트

    • 인증, 사용자, 그룹 관련 단위 테스트가 삭제되었습니다.
  • 기타

    • 코드 스타일 및 패키지 구조 개선, 불필요한 파일 및 메서드 삭제.
    • OpenAPI 문서용 인터페이스가 추가되어 API 명세가 정리되었습니다.
    • 보안 설정에 회원가입 엔드포인트가 인증 없이 접근 가능하도록 추가되었습니다.

@dungbik dungbik requested a review from stoneTiger0912 July 28, 2025 08:19
@dungbik dungbik self-assigned this Jul 28, 2025
@dungbik dungbik added the enhancement New feature or request label Jul 28, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jul 28, 2025

"""

Walkthrough

이번 변경은 인증 및 사용자 관리 도메인의 대대적인 리팩토링과 확장입니다. 인증 주체가 기존 User에서 UserAuth로 분리되었으며, AuthPrinciple DTO가 도입되었습니다. 각종 서비스, 컨트롤러, 레포지토리, DTO, 엔티티가 이에 맞춰 대거 수정, 추가, 삭제되었습니다. 테스트 코드도 전면적으로 제거되었습니다.

Changes

Cohort / File(s) Change Summary
Auth 엔티티 및 레포지토리 도입/변경
src/main/java/project/flipnote/auth/entity/UserAuth.java, .../AccountRole.java, .../AccountStatus.java, .../OAuthLink.java, .../repository/UserAuthRepository.java, .../repository/OAuthLinkRepository.java
인증 정보를 담당하는 UserAuth, OAuthLink 등 신규 엔티티와 레포지토리 추가. 기존 User 기반 구조에서 인증/프로필 분리.
Auth 서비스 및 컨트롤러 리팩토링/확장
.../auth/service/AuthService.java, .../auth/service/OAuthService.java, .../auth/service/TokenVersionService.java, .../auth/controller/AuthController.java, .../auth/controller/OAuthController.java, .../auth/listener/UserWithdrawnEventListener.java
인증 서비스 책임 분리 및 UserAuth 기반 인증 흐름 전환. 회원가입, 비밀번호 변경, 소셜링크 관리 기능 추가. 이벤트 리스너 신설.
JWT 및 시큐리티 계층 전면 수정
.../common/security/dto/AuthPrinciple.java, .../common/security/jwt/JwtComponent.java, .../common/security/jwt/JwtConstants.java, .../common/security/filter/JwtAuthenticationFilter.java, .../common/security/config/SecurityConfig.java
인증 주체를 AuthPrinciple로 통일, JWT 클레임 및 인증 필터, 시큐리티 설정 전면 수정.
User 도메인 분리 및 리팩토링
.../user/entity/UserProfile.java, .../user/repository/UserProfileRepository.java, .../user/repository/UserRepository.java, .../user/service/UserService.java, .../user/controller/UserController.java, .../user/model/*, .../user/exception/UserErrorCode.java, .../user/entity/UserStatus.java, .../user/entity/UserRole.java, .../user/repository/UserOAuthLinkRepository.java
User → UserProfile로 변경, 인증/프로필 분리, 소셜링크·비밀번호·토큰 등 인증 관련 로직 제거, UserOAuthLink 등 관련 코드 삭제.
Group, Infra, 기타 연관 코드 수정
.../group/controller/GroupController.java, .../group/entity/GroupMember.java, .../group/service/GroupService.java, .../infra/email/EmailService.java, .../infra/oauth/OAuthApiClient.java, .../infra/oauth/model/OAuth2UserInfo.java
인증 주체 타입 변경, User → UserProfile로 변경, 불필요/오래된 의존성 제거, 포맷팅 개선.
Auth/Token Redis 저장소 파라미터명 변경
.../auth/repository/SocialLinkTokenRedisRepository.java, .../auth/repository/TokenVersionRedisRepository.java
userId → authId로 파라미터 및 메서드명 통일.
이벤트 및 DTO 신규 추가
.../common/dto/UserCreateCommand.java, .../common/event/UserWithdrawnEvent.java
회원가입/탈퇴 이벤트 및 커맨드 DTO 신규 도입.
테스트 코드 전면 삭제
src/test/java/project/flipnote/auth/service/AuthServiceTest.java, src/test/java/project/flipnote/user/service/UserServiceTest.java, src/test/java/project/flipnote/group/service/GroupServiceTest.java, src/test/java/project/flipnote/fixture/UserFixture.java
기존 User/UserAuth 기반 테스트 코드 및 픽스처 전체 삭제.
마이너 포맷팅/엔드라인/불필요 코드 정리
.../auth/constants/AuthRedisKey.java, .../common/config/OAuthProperties.java, .../common/config/WebConfig.java, .../common/util/PkceUtil.java
엔드라인 추가, 불필요한 콤마 제거, 포맷팅 개선 등.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant AuthController
    participant AuthService
    participant UserService
    participant UserAuthRepository
    participant UserProfileRepository

    Client->>AuthController: POST /register (UserRegisterRequest)
    AuthController->>AuthService: register(req)
    AuthService->>UserService: createUser(command)
    UserService->>UserProfileRepository: save(UserProfile)
    UserService-->>AuthService: userId
    AuthService->>UserAuthRepository: save(UserAuth)
    AuthService-->>AuthController: UserRegisterResponse
    AuthController-->>Client: 201 Created (UserRegisterResponse)
Loading
sequenceDiagram
    participant Client
    participant AuthController
    participant AuthService
    participant UserAuthRepository

    Client->>AuthController: PATCH /password (ChangePasswordRequest)
    AuthController->>AuthService: changePassword(authId, req)
    AuthService->>UserAuthRepository: findByIdAndStatus(authId, ACTIVE)
    AuthService->>UserAuthRepository: updatePassword(email, encodedPassword)
    AuthService->>UserAuthRepository: incrementTokenVersion(authId)
    AuthService-->>AuthController: void
    AuthController-->>Client: 204 No Content
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~90+ minutes

  • 대규모 리팩토링, 신규/삭제/변경 파일 다수, 컨트롤러-서비스-엔티티-레포지토리-시큐리티-테스트 전방위 수정 및 삭제, 도메인 모델 변경, 인증 흐름 전체 재설계.

Possibly related PRs

  • FlipNoteTeam/FlipNote-BE#19: OAuthController, OAuthService의 소셜 로그인 및 연동 흐름 시그니처, 콜백 처리 등에서 직접적으로 코드가 연결됨.
  • FlipNoteTeam/FlipNote-BE#16: AuthRedisKey.java의 SOCIAL_LINK_TOKEN enum 상수 관련 코드가 직접적으로 연관됨.
  • FlipNoteTeam/FlipNote-BE#15: AuthController 및 AuthService의 비밀번호 관련 엔드포인트/로직 추가·수정이 겹침.

Suggested reviewers

  • stoneTiger0912

Poem

🐰
인증과 유저, 분리의 춤,
새로운 Auth가 문을 열었네.
소셜링크, 토큰, 역할도 새로워,
테스트 토끼는 잠시 쉬고,
깔끔해진 코드밭에
토끼는 깡총, 리뷰를 기다려요!
🌱✨
"""

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/user-to-auth

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🔭 Outside diff range comments (1)
src/main/java/project/flipnote/auth/entity/OAuthLink.java (1)

1-26: import 문에 불필요한 의존성이 포함되어 있습니다.

24-25번 라인의 import들이 실제로 사용되지 않고 있습니다.

-import project.flipnote.auth.repository.AuthAccountRepository;
-import project.flipnote.user.entity.UserProfile;
🧹 Nitpick comments (16)
src/main/java/project/flipnote/common/util/PkceUtil.java (2)

14-15: SecureRandom 인스턴스를 static final로 선언하세요

SecureRandom은 thread-safe 합니다. 변경될 필요가 없으므로 static final로 선언해 불변임을 명확히 하고, 혹시 모를 재할당을 방지하는 편이 좋습니다.

-    private static SecureRandom random = new SecureRandom();
+    private static final SecureRandom RANDOM = new SecureRandom();

11-15: 유틸리티 성격에 맞추어 @Component 제거 또는 정적 메서드화 고려

이 클래스는 상태가 없고 외부 의존성도 없으므로 Spring 빈으로 등록할 필요가 없어 보입니다.
옵션:

  1. @Component 제거 후 모든 메서드를 static으로 변경하여 순수 유틸리티 클래스로 사용
  2. 혹은 현재 형태를 유지하되, 테스트 용이성을 위해 인터페이스로 추출

첫 번째 방법이 가장 간단합니다.

-@Component
-public class PkceUtil {
+public final class PkceUtil {

-    public String generateCodeVerifier() {
+    public static String generateCodeVerifier() {
...
-    public String generateCodeChallenge(String codeVerifier) {
+    public static String generateCodeChallenge(String codeVerifier) {
src/main/java/project/flipnote/common/event/UserWithdrawnEvent.java (1)

3-6: 이벤트 기반 아키텍처 도입이 MSA 전환에 적합합니다.

UserWithdrawnEvent 레코드를 통해 사용자 탈퇴 시 도메인 간 결합도를 낮춘 설계가 좋습니다. 사용자 프로필과 인증 계정 상태 업데이트를 비동기적으로 분리할 수 있어 MSA 전환에 유리합니다.

더 견고한 구현을 위해 userId에 대한 검증을 고려해보세요:

public record UserWithdrawnEvent(
-	Long userId
+	@NonNull Long userId
) {
+	public UserWithdrawnEvent {
+		if (userId == null || userId <= 0) {
+			throw new IllegalArgumentException("유효하지 않은 사용자 ID입니다.");
+		}
+	}
}
src/main/java/project/flipnote/common/dto/UserCreateCommand.java (1)

3-11: 검증 어노테이션 추가를 고려해보세요.

관련된 UserRegisterRequest, UserUpdateRequest 클래스들에는 @Email, @NotBlank, @ValidPhone 등의 검증 어노테이션이 있는데, 이 Command 클래스에는 없습니다. 데이터 무결성을 위해 최소한의 검증 어노테이션 추가를 고려해보세요.

다음과 같이 검증 어노테이션을 추가할 수 있습니다:

+import jakarta.validation.constraints.*;
+import project.flipnote.user.validator.ValidPhone;
+
 public record UserCreateCommand(
 	Long userId,
+	@Email @NotBlank
 	String email,
+	@NotBlank
 	String name,
+	@NotBlank
 	String nickname,
+	@NotNull
 	Boolean smsAgree,
+	@ValidPhone
 	String phone,
 	String profileImageUrl
 ) {
src/main/java/project/flipnote/auth/repository/OAuthLinkRepository.java (2)

20-30: JPQL 쿼리에서 별칭 일관성을 개선하세요.

JOIN FETCH를 사용한 쿼리는 좋지만, 별칭이 uol로 되어 있어 이전 UserOAuthLink 시절의 네이밍이 남아있습니다.

	@Query("""
-		SELECT uol
-		FROM OAuthLink uol
-		JOIN FETCH uol.account
-		WHERE uol.provider = :provider
-		AND uol.providerId = :providerId
+		SELECT ol
+		FROM OAuthLink ol
+		JOIN FETCH ol.account
+		WHERE ol.provider = :provider
+		AND ol.providerId = :providerId
		""")

14-14: 데이터베이스 인덱스 최적화를 검토하세요.

existsByAccount_IdAndProviderId 메서드는 복합 조건으로 자주 사용될 것으로 예상됩니다. 성능 최적화를 위해 (account_id, provider_id) 복합 인덱스 생성을 고려해보세요.

src/main/java/project/flipnote/user/repository/UserRepository.java (1)

9-11: 사용자 프로필 조회 메서드 추가를 고려하세요.

현재는 존재성 확인만 가능한데, 실제 서비스에서는 사용자 프로필 조회가 필요할 것입니다.

	boolean existsByEmail(String email);

	boolean existsByPhone(String phone);

+	Optional<UserProfile> findByEmail(String email);
+
+	Optional<UserProfile> findByPhone(String phone);
src/main/java/project/flipnote/common/security/dto/AccountAuth.java (2)

29-38: JWT 클레임 파싱에서 변수명 불일치를 수정하세요.

AccountAuth 레코드의 첫 번째 필드가 accountId인데, JWT 파싱에서는 여전히 userId 변수명을 사용하고 있습니다.

	public static AccountAuth from(Claims claims) {
-		long userId = Long.parseLong(claims.getId());
+		long accountId = Long.parseLong(claims.getId());
		AccountRole userRole = AccountRole.from(
			claims.get(JwtConstants.ROLE, String.class)
		);
		String email = claims.getSubject();
		long tokenVersion = claims.get(JwtConstants.TOKEN_VERSION, Long.class);

-		return new AccountAuth(userId, email, userRole, tokenVersion);
+		return new AccountAuth(accountId, email, userRole, tokenVersion);
	}

17-17: 필드명과 실제 역할의 불일치를 수정하세요.

레코드 필드명이 userRole인데 타입이 AccountRole로 변경되었습니다. 일관성을 위해 필드명도 accountRole로 변경하는 것이 좋겠습니다.

public record AccountAuth(
	Long accountId,
	String email,
-	AccountRole userRole,
+	AccountRole accountRole,
	long tokenVersion
) {

	public Collection<? extends GrantedAuthority> getAuthorities() {
-		return List.of(new SimpleGrantedAuthority("ROLE_" + userRole.name()));
+		return List.of(new SimpleGrantedAuthority("ROLE_" + accountRole.name()));
	}

	public static AccountAuth from(AuthAccount account) {
		return new AccountAuth(account.getId(), account.getEmail(), account.getRole(), account.getTokenVersion());
	}

	public static AccountAuth from(Claims claims) {
		long accountId = Long.parseLong(claims.getId());
-		AccountRole userRole = AccountRole.from(
+		AccountRole accountRole = AccountRole.from(
			claims.get(JwtConstants.ROLE, String.class)
		);
		String email = claims.getSubject();
		long tokenVersion = claims.get(JwtConstants.TOKEN_VERSION, Long.class);

-		return new AccountAuth(accountId, email, userRole, tokenVersion);
+		return new AccountAuth(accountId, email, accountRole, tokenVersion);
	}
}
src/main/java/project/flipnote/auth/entity/AuthAccount.java (1)

1-72: 인증 도메인 분리가 MSA 전환에 적합합니다.

AuthAccount로 인증 관련 데이터만 분리한 설계가 마이크로서비스 아키텍처 전환에 유리합니다. 프로필 정보는 UserProfile로 분리되어 관심사가 명확히 구분되었습니다.

데이터 마이그레이션 시 기존 users 테이블에서 auth_account 테이블로의 데이터 이관 전략과 외래 키 제약 조건 처리 방안을 고려해야 합니다.

src/main/java/project/flipnote/auth/controller/AuthController.java (1)

140-157: 소셜 연동 관리 엔드포인트가 잘 설계되었습니다.

RESTful 규약에 따라 GET과 DELETE 메서드를 적절히 사용했으며, 인증 확인도 적절합니다.

삭제 작업 시 해당 소셜 링크가 현재 사용자의 것인지 서비스 레이어에서 추가 검증이 필요할 수 있습니다.

src/main/java/project/flipnote/common/security/jwt/JwtComponent.java (1)

75-81: 메서드명이 일관성 있게 변경되지 않았습니다.

메서드명이 여전히 extractUserAuthFromToken으로 되어 있지만, 반환 타입은 AccountAuth입니다. 일관성을 위해 메서드명을 extractAccountAuthFromToken으로 변경하는 것을 고려해보세요.

-public AccountAuth extractUserAuthFromToken(String token) {
+public AccountAuth extractAccountAuthFromToken(String token) {
src/main/java/project/flipnote/user/controller/UserController.java (1)

52-58: 경로 변수명과 일관성 문제가 있습니다.

경로 변수가 여전히 userId로 되어 있는데, 전체적인 리팩토링 방향을 고려하면 accountId로 변경하는 것이 일관성 있을 것 같습니다. 다만, 이는 API 호환성에 영향을 줄 수 있으므로 신중한 결정이 필요합니다.

-@GetMapping("/{userId}")
+@GetMapping("/{accountId}")
 public ResponseEntity<UserInfoResponse> getUserInfo(
-    @PathVariable("userId") Long userId
+    @PathVariable("accountId") Long accountId
 ) {
-    UserInfoResponse res = userService.getUserInfo(userId);
+    UserInfoResponse res = userService.getUserInfo(accountId);
     return ResponseEntity.ok(res);
 }
src/main/java/project/flipnote/user/service/UserService.java (1)

88-96: 전화번호 중복 검증 메서드의 접근 제한자 변경

validatePhoneDuplicate 메서드가 public으로 변경되었는데, 이는 AuthService에서 사용하기 위한 것으로 보입니다. 도메인 간 직접 호출보다는 별도의 검증 서비스나 이벤트 기반 검증을 고려해보세요.

MSA 전환을 고려한다면, 도메인 간 직접적인 의존성보다는 API 호출이나 이벤트 기반 검증이 더 적합할 수 있습니다.

src/main/java/project/flipnote/auth/service/AuthService.java (2)

3-42: 도메인 간 의존성이 증가했습니다.

Auth 도메인이 User 도메인의 서비스와 모델을 직접 참조하고 있습니다. MSA 전환을 고려한다면 이러한 직접적인 의존성을 줄이는 것이 좋습니다.


190-194: validatePasswordMatch 메서드의 접근 제한자

이 메서드가 public으로 선언되어 있는데, 클래스 내부에서만 사용된다면 private으로 변경하는 것이 좋습니다.

-public void validatePasswordMatch(String rawPassword, String encodedPassword) {
+private void validatePasswordMatch(String rawPassword, String encodedPassword) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 07329d8 and 904c970.

📒 Files selected for processing (53)
  • src/main/java/project/flipnote/auth/constants/AuthRedisKey.java (1 hunks)
  • src/main/java/project/flipnote/auth/controller/AuthController.java (3 hunks)
  • src/main/java/project/flipnote/auth/controller/OAuthController.java (2 hunks)
  • src/main/java/project/flipnote/auth/entity/AccountRole.java (1 hunks)
  • src/main/java/project/flipnote/auth/entity/AccountStatus.java (1 hunks)
  • src/main/java/project/flipnote/auth/entity/AuthAccount.java (3 hunks)
  • src/main/java/project/flipnote/auth/entity/OAuthLink.java (3 hunks)
  • src/main/java/project/flipnote/auth/exception/AuthErrorCode.java (1 hunks)
  • src/main/java/project/flipnote/auth/listener/UserWithdrawnEventListener.java (1 hunks)
  • src/main/java/project/flipnote/auth/model/ChangePasswordRequest.java (1 hunks)
  • src/main/java/project/flipnote/auth/model/UserRegisterRequest.java (2 hunks)
  • src/main/java/project/flipnote/auth/model/UserRegisterResponse.java (1 hunks)
  • src/main/java/project/flipnote/auth/repository/AuthAccountRepository.java (1 hunks)
  • src/main/java/project/flipnote/auth/repository/OAuthLinkRepository.java (1 hunks)
  • src/main/java/project/flipnote/auth/repository/SocialLinkTokenRedisRepository.java (1 hunks)
  • src/main/java/project/flipnote/auth/repository/TokenVersionRedisRepository.java (1 hunks)
  • src/main/java/project/flipnote/auth/service/AuthService.java (6 hunks)
  • src/main/java/project/flipnote/auth/service/EmailVerificationService.java (0 hunks)
  • src/main/java/project/flipnote/auth/service/OAuthService.java (4 hunks)
  • src/main/java/project/flipnote/auth/service/TokenVersionService.java (1 hunks)
  • src/main/java/project/flipnote/common/config/OAuthProperties.java (1 hunks)
  • src/main/java/project/flipnote/common/config/WebConfig.java (1 hunks)
  • src/main/java/project/flipnote/common/dto/UserCreateCommand.java (1 hunks)
  • src/main/java/project/flipnote/common/event/UserWithdrawnEvent.java (1 hunks)
  • src/main/java/project/flipnote/common/security/config/SecurityConfig.java (1 hunks)
  • src/main/java/project/flipnote/common/security/dto/AccountAuth.java (1 hunks)
  • src/main/java/project/flipnote/common/security/filter/JwtAuthenticationFilter.java (3 hunks)
  • src/main/java/project/flipnote/common/security/jwt/JwtComponent.java (3 hunks)
  • src/main/java/project/flipnote/common/util/PkceUtil.java (1 hunks)
  • src/main/java/project/flipnote/group/controller/GroupController.java (2 hunks)
  • src/main/java/project/flipnote/group/entity/Group.java (2 hunks)
  • src/main/java/project/flipnote/group/entity/GroupMember.java (2 hunks)
  • src/main/java/project/flipnote/group/service/GroupService.java (4 hunks)
  • src/main/java/project/flipnote/infra/email/EmailService.java (1 hunks)
  • src/main/java/project/flipnote/infra/oauth/OAuthApiClient.java (3 hunks)
  • src/main/java/project/flipnote/infra/oauth/model/OAuth2UserInfo.java (1 hunks)
  • src/main/java/project/flipnote/user/controller/UserController.java (2 hunks)
  • src/main/java/project/flipnote/user/entity/UserProfile.java (1 hunks)
  • src/main/java/project/flipnote/user/entity/UserRole.java (0 hunks)
  • src/main/java/project/flipnote/user/entity/UserStatus.java (0 hunks)
  • src/main/java/project/flipnote/user/exception/UserErrorCode.java (1 hunks)
  • src/main/java/project/flipnote/user/model/MyInfoResponse.java (2 hunks)
  • src/main/java/project/flipnote/user/model/SocialLinkResponse.java (2 hunks)
  • src/main/java/project/flipnote/user/model/SocialLinksResponse.java (1 hunks)
  • src/main/java/project/flipnote/user/model/UserInfoResponse.java (1 hunks)
  • src/main/java/project/flipnote/user/model/UserUpdateResponse.java (2 hunks)
  • src/main/java/project/flipnote/user/repository/UserOAuthLinkRepository.java (0 hunks)
  • src/main/java/project/flipnote/user/repository/UserRepository.java (1 hunks)
  • src/main/java/project/flipnote/user/service/UserService.java (4 hunks)
  • src/test/java/project/flipnote/auth/service/AuthServiceTest.java (0 hunks)
  • src/test/java/project/flipnote/fixture/UserFixture.java (1 hunks)
  • src/test/java/project/flipnote/group/service/GroupServiceTest.java (0 hunks)
  • src/test/java/project/flipnote/user/service/UserServiceTest.java (8 hunks)
💤 Files with no reviewable changes (6)
  • src/main/java/project/flipnote/auth/service/EmailVerificationService.java
  • src/main/java/project/flipnote/user/entity/UserRole.java
  • src/test/java/project/flipnote/group/service/GroupServiceTest.java
  • src/main/java/project/flipnote/user/entity/UserStatus.java
  • src/main/java/project/flipnote/user/repository/UserOAuthLinkRepository.java
  • src/test/java/project/flipnote/auth/service/AuthServiceTest.java
🧰 Additional context used
🧬 Code Graph Analysis (19)
src/main/java/project/flipnote/infra/oauth/model/OAuth2UserInfo.java (1)
src/main/java/project/flipnote/infra/oauth/model/GoogleUserInfo.java (1)
  • GoogleUserInfo (7-30)
src/main/java/project/flipnote/auth/model/UserRegisterResponse.java (1)
src/main/java/project/flipnote/user/model/UserRegisterResponse.java (1)
  • UserRegisterResponse (3-10)
src/main/java/project/flipnote/auth/model/ChangePasswordRequest.java (1)
src/main/java/project/flipnote/user/model/ChangePasswordRequest.java (1)
  • ChangePasswordRequest (5-13)
src/main/java/project/flipnote/common/event/UserWithdrawnEvent.java (2)
src/main/java/project/flipnote/user/model/UserRegisterResponse.java (1)
  • UserRegisterResponse (3-10)
src/main/java/project/flipnote/user/entity/User.java (1)
  • User (20-105)
src/main/java/project/flipnote/auth/entity/AccountStatus.java (3)
src/main/java/project/flipnote/auth/entity/AuthAccount.java (1)
  • Getter (18-72)
src/main/java/project/flipnote/user/entity/UserStatus.java (1)
  • UserStatus (5-8)
src/main/java/project/flipnote/user/entity/User.java (1)
  • User (20-105)
src/main/java/project/flipnote/common/dto/UserCreateCommand.java (3)
src/main/java/project/flipnote/user/model/UserUpdateRequest.java (1)
  • UserUpdateRequest (8-25)
src/main/java/project/flipnote/user/model/UserRegisterRequest.java (1)
  • UserRegisterRequest (10-35)
src/main/java/project/flipnote/user/entity/User.java (1)
  • User (20-105)
src/main/java/project/flipnote/user/model/UserUpdateResponse.java (2)
src/main/java/project/flipnote/user/model/UserUpdateRequest.java (1)
  • UserUpdateRequest (8-25)
src/main/java/project/flipnote/user/entity/User.java (1)
  • User (20-105)
src/main/java/project/flipnote/auth/controller/OAuthController.java (2)
src/main/java/project/flipnote/common/security/dto/UserAuth.java (1)
  • UserAuth (14-39)
src/main/java/project/flipnote/user/entity/UserOAuthLink.java (1)
  • UserOAuthLink (20-52)
src/main/java/project/flipnote/user/model/MyInfoResponse.java (1)
src/main/java/project/flipnote/user/entity/User.java (1)
  • User (20-105)
src/test/java/project/flipnote/fixture/UserFixture.java (2)
src/test/java/project/flipnote/group/service/GroupServiceTest.java (1)
  • before (65-72)
src/main/java/project/flipnote/user/entity/User.java (1)
  • User (20-105)
src/main/java/project/flipnote/group/controller/GroupController.java (2)
src/test/java/project/flipnote/group/service/GroupServiceTest.java (2)
  • before (65-72)
  • GroupServiceTest (37-120)
src/main/java/project/flipnote/common/security/dto/UserAuth.java (1)
  • UserAuth (14-39)
src/main/java/project/flipnote/auth/repository/AuthAccountRepository.java (1)
src/main/java/project/flipnote/auth/repository/PasswordResetRedisRepository.java (1)
  • PasswordResetRedisRepository (16-71)
src/main/java/project/flipnote/group/service/GroupService.java (2)
src/test/java/project/flipnote/group/service/GroupServiceTest.java (1)
  • before (65-72)
src/main/java/project/flipnote/user/entity/User.java (1)
  • User (20-105)
src/main/java/project/flipnote/auth/entity/AuthAccount.java (3)
src/main/java/project/flipnote/user/entity/User.java (4)
  • User (20-105)
  • update (95-100)
  • unregister (83-89)
  • changePassword (102-104)
src/main/java/project/flipnote/common/security/dto/UserAuth.java (1)
  • UserAuth (14-39)
src/main/java/project/flipnote/user/entity/UserOAuthLink.java (1)
  • UserOAuthLink (20-52)
src/test/java/project/flipnote/user/service/UserServiceTest.java (1)
src/test/java/project/flipnote/fixture/UserFixture.java (1)
  • UserFixture (7-26)
src/main/java/project/flipnote/common/security/jwt/JwtComponent.java (2)
src/main/java/project/flipnote/common/security/dto/UserAuth.java (1)
  • UserAuth (14-39)
src/main/java/project/flipnote/user/entity/User.java (1)
  • User (20-105)
src/main/java/project/flipnote/user/controller/UserController.java (1)
src/main/java/project/flipnote/user/entity/User.java (1)
  • User (20-105)
src/main/java/project/flipnote/auth/service/AuthService.java (1)
src/test/java/project/flipnote/auth/service/AuthServiceTest.java (2)
  • AuthServiceTest (44-410)
  • success (379-394)
src/main/java/project/flipnote/user/model/SocialLinkResponse.java (3)
src/main/java/project/flipnote/user/entity/UserOAuthLink.java (2)
  • UserOAuthLink (20-52)
  • UserOAuthLink (46-51)
src/main/java/project/flipnote/user/repository/UserOAuthLinkRepository.java (1)
  • UserOAuthLinkRepository (7-10)
src/main/java/project/flipnote/user/entity/User.java (1)
  • User (20-105)
🔇 Additional comments (72)
src/main/java/project/flipnote/common/config/OAuthProperties.java (1)

49-49: 파일 끝에 개행 추가 👍

POSIX 규격에 맞춰 EOF 개행을 추가한 점 확인했습니다.
코드 스타일 일관성 유지에 도움이 됩니다.

src/main/java/project/flipnote/common/config/WebConfig.java (1)

21-22: 파일 끝 개행 추가로 POSIX 규약 충족

텍스트 파일을 개행으로 종료하도록 수정되어 리눅스 계열 도구에서 경고가 발생하지 않습니다. 기능적 변경은 없으며, 스타일 가이드 측면에서 긍정적인 개선입니다.

src/main/java/project/flipnote/common/util/PkceUtil.java (1)

31-31: 마지막 줄 개행 추가 확인

파일 끝에 개행을 추가한 변경만 이루어졌습니다. 스타일 가이드에 부합하므로 문제 없습니다.

src/main/java/project/flipnote/auth/model/UserRegisterResponse.java (1)

1-1: MSA 전환을 위한 패키지 구조 개선이 적절합니다.

사용자 등록 응답 모델을 user.model에서 auth.model 패키지로 이동한 것은 인증 관련 기능을 분리하여 MSA 전환에 유리한 구조로 개선하는 올바른 접근입니다.

src/main/java/project/flipnote/auth/entity/AccountStatus.java (1)

5-8: 중복된 UserStatus enum 사용 없음 확인

rg -A5 "UserStatus" --type java 실행 결과, UserStatus enum에 대한 참조가 전혀 발견되지 않았습니다. 모든 이전 UserStatus 참조가 새로운 AccountStatus로 성공적으로 마이그레이션된 것으로 확인되며, 중복 이슈는 없습니다.

src/main/java/project/flipnote/auth/model/UserRegisterRequest.java (2)

1-1: 인증 모듈로의 패키지 이동이 적절합니다.

사용자 등록 요청 모델을 auth.model 패키지로 이동한 것은 MSA 전환을 위한 도메인 분리에 부합합니다.


37-39: 확인 완료: UserCreateCommand 정의 및 사용처 적합

  • project/flipnote/common/dto/UserCreateCommand.java에 record로 정의되어 있습니다.
  • UserRegisterRequest.toCommand(Long accountId)에서 전달하는 인자(accountId, email, name, nickname, smsAgree, getNormalizedPhone(), profileImageUrl)와 record 필드 순서가 일치합니다.
  • AuthService 및 UserService에서 의도한 대로 사용되고 있으므로 추가 수정은 필요 없습니다.
src/main/java/project/flipnote/group/entity/GroupMember.java (1)

18-18: 관련 서비스 및 컨트롤러 검증 완료: 추가 수정 불필요

서비스와 레포지토리에서 UserProfile 연관관계가 올바르게 반영되었으며, 컨트롤러 레이어에는 GroupMember를 직접 참조하는 코드가 없어 추가 변경이 필요하지 않습니다.

  • GroupService
    • findUser(accountAuth)saveGroupOwner(Group, UserProfile) 로직에서 UserProfile 연관관계 정상 작동 확인
  • GroupMemberRepository
    • JpaRepository<GroupMember, Long> 확장부 정상
  • 컨트롤러
    • GroupMember 직접 참조 위치 없음 (검색 결과)
src/main/java/project/flipnote/user/entity/UserProfile.java (3)

1-22: 도메인 분리를 위한 새로운 엔티티 설계가 우수합니다.

인증 관련 데이터(AuthAccount)와 사용자 프로필 데이터(UserProfile)를 분리한 것은 MSA 전환에 매우 적합한 설계입니다. 각 엔티티가 명확한 책임을 가지게 되었습니다.


44-49: 프로필 업데이트 메서드가 적절합니다.

변경 가능한 필드들(nickname, phone, smsAgree, profileImageUrl)만을 업데이트하는 메서드 설계가 적절하며, 불변 필드들(email, name)은 보호되고 있습니다.


24-25: UserProfile 생성 로직 및 ID 할당 방식 재확인 필요
UserProfile 엔티티에 @GeneratedValue가 없어 수동 ID 할당으로 보이지만, 실제 생성·저장 지점과 AuthAccount와의 연관관계 매핑이 코드상 확인되지 않습니다. 아래 항목을 점검해주세요:

  • 서비스(또는 핸들러)에서 new UserProfile(...) 또는 UserProfile.builder() 호출 위치
  • UserProfileRepository.save(…) 등 저장 로직
  • AuthAccount 엔티티 내 @OneToOne(또는 @MapsId) 매핑 및 cascade 설정
src/main/java/project/flipnote/infra/email/EmailService.java (1)

5-7: 형식 변경만 존재 – 추가 조치 불필요

공백 한 줄 추가만 이루어졌으며 기능적 영향이 없습니다.

src/main/java/project/flipnote/infra/oauth/model/OAuth2UserInfo.java (1)

4-10: 형식 변경만 존재 – 추가 조치 불필요

메서드 사이 공백 추가 외에 변경 사항이 없습니다.

src/main/java/project/flipnote/auth/constants/AuthRedisKey.java (1)

16-16: 컴파일 오류 수정 완료

마지막 enum 항목 뒤의 세미콜론 추가로 컴파일 오류가 해결되었습니다. TTL(180초) 값도 요구사항에 부합한다면 그대로 유지해도 무방합니다.

src/main/java/project/flipnote/auth/model/ChangePasswordRequest.java (1)

1-1: 패키지 참조 확인 완료: ChangePasswordRequest 이전 경로 미사용

rg -n "project\.flipnote\.user\.model\.ChangePasswordRequest"로 검색해도 결과가 없었고, 패키지 전체 검색에서도 해당 클래스에 대한 구(舊)경로 참조는 발견되지 않았습니다.

  • 별도의 수정 없이 안전합니다.
src/main/java/project/flipnote/group/entity/Group.java (1)

11-13: 형식 변경만 존재 – 추가 조치 불필요

import 정리 및 트레일링 콤마 제거만 이루어졌습니다.

src/main/java/project/flipnote/user/exception/UserErrorCode.java (1)

15-15: MSA 전환을 위한 도메인 분리가 적절히 반영되었습니다.

SOCIAL_LINK_NOT_FOUND 에러 코드를 AuthErrorCode로 이동한 것은 소셜 연동 기능을 인증 도메인으로 분리하는 리팩토링 목표와 일치합니다. 사용자 프로필 관련 에러 코드만 남겨둔 것이 적절합니다.

src/main/java/project/flipnote/common/security/config/SecurityConfig.java (1)

61-61: 회원가입 엔드포인트에 대한 보안 설정이 적절합니다.

새로 추가된 "/*/auth/register" 엔드포인트를 permitAll()에 포함한 것이 올바릅니다. 기존 인증 관련 엔드포인트들과 함께 그룹화되어 있고, 와일드카드 패턴을 통한 버전 지원도 일관성 있게 적용되었습니다.

src/main/java/project/flipnote/user/model/MyInfoResponse.java (2)

7-7: 도메인 분리를 위한 임포트 변경이 적절합니다.

User에서 UserProfile로 임포트를 변경한 것이 사용자 프로필과 인증 도메인을 분리하는 리팩토링 목표와 일치합니다.


25-37: 팩토리 메서드 업데이트가 올바르게 구현되었습니다.

from() 메서드의 매개변수 타입을 UserProfile로 변경하고 해당 게터 메서드들을 사용하도록 구현한 것이 적절합니다. API 응답 구조는 유지하면서 내부 도메인 모델만 변경되어 기존 클라이언트와의 호환성도 보장됩니다.

src/main/java/project/flipnote/auth/exception/AuthErrorCode.java (1)

25-26: 소셜 연동 관리의 Auth 도메인 이관이 적절합니다.

소셜 연동 계정 관리 책임이 User 도메인에서 Auth 도메인으로 이관되면서 SOCIAL_LINK_NOT_FOUND 에러 코드가 추가된 것이 MSA 전환을 위한 도메인 분리 목적에 부합합니다. 에러 메시지와 HTTP 상태 코드도 적절하게 설정되어 있습니다.

src/main/java/project/flipnote/user/model/UserUpdateResponse.java (2)

3-3: UserProfile 엔티티로의 전환이 도메인 분리 목적에 적합합니다.

User 엔티티에서 UserProfile 엔티티로 변경된 것이 인증 관심사와 사용자 프로필 관심사를 분리하는 MSA 구조 개선에 부합합니다.


13-17: UserProfile 엔티티에 클래스 레벨 @Getter 어노테이션이 적용되어 있어 getId(), getNickname(), getPhone(), isSmsAgree(), getProfileImageUrl() 메서드가 자동 생성됩니다.
해당 factory 메서드는 별도 수정 없이 정상 동작합니다.

src/main/java/project/flipnote/user/model/UserInfoResponse.java (2)

3-3: 도메인 분리에 따른 일관된 엔티티 변경입니다.

UserUpdateResponse와 동일하게 User에서 UserProfile로 변경된 것이 일관된 리팩토링 패턴을 보여줍니다.


11-13: UserProfile 엔티티의 메서드 구현 확인이 필요합니다.

factory 메서드에서 호출하는 getId(), getNickname(), getProfileImageUrl() 메서드들이 UserProfile 엔티티에 적절히 구현되어 있는지 확인해주세요.

src/main/java/project/flipnote/common/dto/UserCreateCommand.java (1)

1-13: 도메인 분리를 위한 Command DTO 구조가 적절합니다.

AuthService에서 UserService로 사용자 생성을 위임하기 위한 Command 패턴 적용이 MSA 구조 개선에 적합합니다. 불변 객체로 설계된 점도 좋습니다.

src/test/java/project/flipnote/fixture/UserFixture.java (2)

5-5: UserProfile 엔티티로의 테스트 픽스처 업데이트가 적절합니다.

User에서 UserProfile로 변경하면서 인증 관련 필드(password)가 제거된 것이 도메인 분리 목적에 부합합니다.


12-25: UserFixture 변경으로 인한 테스트 영향 없음 확인
UserFixture.createActiveUser()를 사용하는 모든 테스트(UserServiceTest 등)에서 getRole(), getTokenVersion(), getStatus() 호출을 검색한 결과, 해당 메서드가 사용된 부분이 없으므로 추가 수정은 필요하지 않습니다.

src/main/java/project/flipnote/user/model/SocialLinkResponse.java (1)

7-7: 도메인 모델 리팩토링이 올바르게 적용되었습니다.

UserOAuthLink에서 OAuthLink로의 변경이 일관성 있게 적용되어 있으며, 인증 관련 엔티티가 auth 패키지로 적절히 이동되었습니다.

Also applies to: 19-19

src/main/java/project/flipnote/user/model/SocialLinksResponse.java (1)

5-5: 일관된 타입 변경이 적용되었습니다.

OAuthLink 엔티티 사용으로의 변경이 올바르게 적용되어 있으며, 리스트 처리 로직도 적절히 업데이트되었습니다.

Also applies to: 11-11

src/main/java/project/flipnote/auth/controller/OAuthController.java (1)

28-28: AccountAuth가 일관되게 적용되었으며, UserAuth는 더 이상 존재하지 않습니다.

OAuthController와 관련 호출부가 모두 AccountAuth로 정상 업데이트되어 있어 추가 검증이 필요 없습니다.

src/main/java/project/flipnote/group/controller/GroupController.java (1)

13-13: 컨트롤러 인증 타입 변경 검토 완료

GroupController의 인증 타입이 UserAuth에서 AccountAuth로 일관되게 변경되었습니다.
전체 테스트 코드에서도 UserAuth 사용이 발견되지 않아 추가 수정이 필요하지 않습니다.

src/main/java/project/flipnote/infra/oauth/OAuthApiClient.java (1)

30-35: 코드 스타일 개선이 적절히 적용되었습니다.

메서드 파라미터 포맷팅과 TypeReference 사용법이 일관되게 개선되어 가독성이 향상되었습니다.

Also applies to: 52-54, 68-69

src/main/java/project/flipnote/auth/listener/UserWithdrawnEventListener.java (2)

1-16: 패키지 구조와 import문이 적절합니다.

MSA 전환을 위한 리팩토링에 맞게 auth 도메인으로 적절히 분리되었고, 필요한 Spring 어노테이션들과 의존성들이 올바르게 import되었습니다.


17-22: 컴포넌트 선언이 적절합니다.

Lombok을 활용한 의존성 주입과 로깅 설정이 올바르게 구성되었습니다. AuthAccountRepository 의존성도 새로운 account 기반 구조에 맞게 적절히 설정되었습니다.

src/main/java/project/flipnote/auth/entity/OAuthLink.java (3)

32-38: 테이블명 변경이 MSA 전환 목적에 부합합니다.

user_oauth_link에서 oauth_link로 변경된 것은 도메인 분리에 적합하며, 인덱스 설정도 적절히 유지되었습니다.


51-52: 연관관계 설정이 올바르게 변경되었습니다.

User에서 AuthAccount로의 연관관계 변경과 조인 컬럼명 변경(user_idaccount_id)이 새로운 account 기반 구조에 맞게 적절히 수정되었습니다.


59-63: 생성자 파라미터가 일관성 있게 변경되었습니다.

Builder 메서드의 파라미터가 User에서 AuthAccount로 적절히 변경되어 새로운 도메인 모델과 일치합니다.

src/main/java/project/flipnote/auth/service/TokenVersionService.java (3)

8-16: 의존성 변경이 적절합니다.

UserRepository에서 AuthAccountRepository로의 변경이 새로운 account 기반 인증 구조에 맞게 올바르게 수정되었습니다.


18-27: 메서드 시그니처와 로직이 일관성 있게 변경되었습니다.

userId에서 accountId로의 파라미터명 변경과 관련 로직들이 새로운 명명 규칙에 맞게 적절히 수정되었습니다. Redis 캐싱 로직도 올바르게 유지되었습니다.


29-32: 토큰 버전 증가 로직이 올바르게 업데이트되었습니다.

accountId 기반으로 토큰 버전을 증가시키고 Redis 캐시를 삭제하는 로직이 새로운 도메인 모델에 맞게 적절히 변경되었습니다.

src/main/java/project/flipnote/auth/repository/SocialLinkTokenRedisRepository.java (2)

18-23: 메서드 파라미터명이 일관성 있게 변경되었습니다.

userId에서 accountId로의 파라미터명 변경이 새로운 account 기반 명명 규칙에 맞게 적절히 수정되었고, Redis 저장 로직도 올바르게 유지되었습니다.


25-32: 메서드명과 내부 로직이 올바르게 업데이트되었습니다.

findUserIdByToken에서 findAccountIdByToken으로의 메서드명 변경과 내부 변수명들이 새로운 도메인 모델에 맞게 일관성 있게 수정되었습니다. Redis 조회 로직은 적절히 유지되었습니다.

src/main/java/project/flipnote/common/security/filter/JwtAuthenticationFilter.java (3)

18-18: import문이 새로운 DTO에 맞게 적절히 변경되었습니다.

UserAuth에서 AccountAuth로의 import 변경이 새로운 account 기반 인증 구조에 맞게 올바르게 수정되었습니다.


38-41: 변수명과 메서드 호출이 일관성 있게 변경되었습니다.

userAuth에서 accountAuth로의 변수명 변경이 새로운 명명 규칙에 맞게 적절히 수정되었고, JWT 컴포넌트 호출도 올바르게 유지되었습니다.


55-57: 인증 설정 메서드가 올바르게 업데이트되었습니다.

setAuthentication 메서드의 파라미터 타입이 AccountAuth로 변경되었고, Spring Security의 UsernamePasswordAuthenticationToken 생성 시 새로운 DTO를 올바르게 사용하고 있습니다.

src/main/java/project/flipnote/auth/repository/OAuthLinkRepository.java (1)

12-18: 리포지토리 메서드 구성이 적절합니다.

OAuth 링크 관리에 필요한 핵심 기능들이 잘 정의되어 있습니다. 계정별 OAuth 링크 조회, 존재성 확인 등 필수 메서드들이 포함되어 있어 좋습니다.

src/main/java/project/flipnote/user/repository/UserRepository.java (1)

5-7: 도메인 분리가 잘 이루어졌습니다.

User에서 UserProfile로 변경하여 인증과 사용자 프로필 관리를 명확히 분리한 것이 MSA 전환에 적합합니다. 인증 관련 책임은 AuthAccountRepository로 이관되어 단일 책임 원칙을 잘 준수하고 있습니다.

src/main/java/project/flipnote/auth/repository/AuthAccountRepository.java (2)

13-19: 인증 관련 메서드들이 잘 구성되어 있습니다.

계정 존재성 확인, 상태별 조회 등 인증에 필요한 핵심 기능들이 적절히 정의되어 있습니다. AccountStatus를 활용한 상태 기반 조회도 좋은 설계입니다.


21-23: 비밀번호 해싱 처리 확인 완료

AuthService(src/main/java/project/flipnote/auth/service/AuthService.java:152–153)에서

String encodedPassword = passwordEncoder.encode(req.password());
authAccountRepository.updatePassword(email, encodedPassword);

를 통해 해싱된 값이 전달되고 있으므로, 비밀번호가 안전하게 업데이트되고 있습니다. 추가 수정은 필요 없습니다.

src/main/java/project/flipnote/auth/repository/TokenVersionRedisRepository.java (1)

18-36: 일관성 있는 네이밍 변경이 잘 이루어졌습니다.

userId에서 accountId로의 파라미터명 변경이 모든 메서드에 일관성 있게 적용되었습니다. 도메인 모델 변경에 따른 적절한 리팩토링입니다.

src/main/java/project/flipnote/common/security/dto/AccountAuth.java (2)

14-19: 도메인 모델 변경이 일관성 있게 적용되었습니다.

UserAuth에서 AccountAuth로의 변경과 함께 필드명과 타입이 새로운 도메인 모델에 맞게 적절히 업데이트되었습니다.


25-27: 팩토리 메서드가 적절히 업데이트되었습니다.

AuthAccount 엔티티로부터 AccountAuth 생성하는 로직이 올바르게 구현되어 있습니다.

src/main/java/project/flipnote/auth/service/OAuthService.java (3)

46-65: OAuth 인증 URI 생성 로직이 적절합니다.

AccountAuth 기반으로 상태 토큰을 생성하고 PKCE 플로우를 올바르게 구현했습니다.


67-91: 소셜 계정 연동 로직이 견고합니다.

Redis를 통한 상태 토큰 검증, 중복 연동 체크, 그리고 getReferenceById를 사용한 효율적인 엔티티 참조가 잘 구현되었습니다.


119-126: 상태 토큰 생성 로직이 안전합니다.

인증되지 않은 요청에 대한 null 처리와 UUID를 사용한 안전한 토큰 생성이 적절합니다.

src/main/java/project/flipnote/group/service/GroupService.java (1)

114-122: 그룹 소유자 저장 로직이 적절합니다.

UserProfile 엔티티 사용으로의 변경이 일관성 있게 적용되었습니다.

src/main/java/project/flipnote/auth/controller/AuthController.java (2)

46-50: 회원가입 엔드포인트가 적절히 구현되었습니다.

POST 메서드와 201 CREATED 상태 코드 사용이 RESTful 규약에 부합합니다.


131-138: 비밀번호 변경 엔드포인트가 안전하게 구현되었습니다.

인증된 사용자만 접근 가능하고 PATCH 메서드를 적절히 사용했습니다.

src/test/java/project/flipnote/user/service/UserServiceTest.java (3)

45-46: 테스트가 새로운 도메인 모델에 맞게 업데이트되었습니다.

User에서 UserProfile로의 변경이 일관성 있게 적용되었습니다.

Also applies to: 69-70, 105-106, 127-128, 162-163


51-51: 테스트가 서비스 구현과 일치하지만 상태 검증 누락 문제를 포함합니다.

findById 사용은 현재 서비스 구현과 일치하나, 앞서 지적한 사용자 상태 검증 누락 문제가 테스트에도 반영되어 있습니다. 서비스 수정 후 테스트도 함께 업데이트가 필요합니다.

Also applies to: 75-75, 95-95, 111-111, 129-129, 147-147, 163-163, 177-177


1-184: 인증 관련 테스트 이동 여부 확인 필요

UserServiceTest에서 제거된 인증, 비밀번호 변경, 소셜 연동 관련 테스트가 auth 모듈 내 AuthServiceTest.java 또는 다른 테스트 파일로 정상적으로 이관되었는지 확인해주세요. 누락된 테스트로 인한 회귀가 없도록 아래 사항을 검증해 주세요.

  • auth 모듈의 테스트 디렉토리(예: src/test/java/project/flipnote/auth) 내 AuthServiceTest.java 파일 존재 여부
  • 해당 파일 또는 관련 테스트 클래스에 회원가입(register), 비밀번호 변경(changePassword), 소셜 연동(socialLink) 관련 테스트 메서드 포함 여부
src/main/java/project/flipnote/common/security/jwt/JwtComponent.java (4)

15-20: 임포트 변경이 올바르게 적용되었습니다.

User 기반에서 Account 기반으로의 전환이 적절히 반영되었습니다.


35-45: 토큰 생성 메서드가 새로운 도메인 모델에 맞게 잘 리팩토링되었습니다.

AuthAccountAccountAuth를 사용하는 두 가지 오버로드 메서드가 적절히 구현되었습니다.


61-73: 토큰 클레임 설정이 올바르게 업데이트되었습니다.

accountId, email, userRole, tokenVersion 필드가 새로운 AccountAuth 구조에 맞게 적절히 설정됩니다.


108-115: 토큰 검증 로직이 새로운 Account 모델에 맞게 적절히 수정되었습니다.

accountId를 사용한 토큰 버전 검증이 올바르게 구현되었습니다.

src/main/java/project/flipnote/user/controller/UserController.java (2)

15-15: AccountAuth 임포트가 올바르게 변경되었습니다.

새로운 인증 모델에 맞게 적절히 업데이트되었습니다.


30-33: 회원 탈퇴 메서드가 새로운 인증 모델에 맞게 잘 수정되었습니다.

AccountAuthaccountId를 사용하여 일관성 있게 구현되었습니다.

src/main/java/project/flipnote/user/service/UserService.java (2)

5-12: 이벤트 기반 아키텍처를 위한 임포트가 적절히 추가되었습니다.

MSA 전환을 위한 이벤트 기반 통신 구조가 잘 반영되었습니다.


46-49: 이벤트 기반 회원 탈퇴 처리가 잘 구현되었습니다.

직접적인 상태 변경 대신 이벤트 발행을 통한 느슨한 결합이 MSA 아키텍처에 적합합니다.

src/main/java/project/flipnote/auth/service/AuthService.java (2)

158-167: 비밀번호 변경 시 토큰 버전 증가가 적절히 구현되었습니다.

비밀번호 변경 후 기존 토큰을 무효화하는 보안 조치가 잘 적용되었습니다.


175-182: 소셜 링크 삭제 시 권한 검증이 적절히 구현되었습니다.

계정 ID와 소셜 링크 ID를 모두 확인하여 소유권을 검증하는 것이 보안상 올바른 접근입니다.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (4)
src/main/java/project/flipnote/auth/listener/UserWithdrawnEventListener.java (2)

24-33: 이벤트 처리 로직의 동시성 및 트랜잭션 관리가 필요합니다.

현재 구현에서 findByIdAndStatuswithdraw 호출 사이에 race condition이 발생할 수 있으며, 트랜잭션 경계가 명확하지 않습니다.


35-38: 복구 메서드의 로깅을 국제화하고 개선해야 합니다.

로그 메시지가 한국어로 되어 있어 국제화 관점에서 개선이 필요하고, 더 구체적인 컨텍스트 정보가 필요합니다.

src/main/java/project/flipnote/auth/service/AuthService.java (2)

58-61: MSA 전환에 부적합한 서비스 간 직접 의존성

UserService를 직접 의존성으로 주입받는 것은 MSA 원칙에 위배됩니다. 인증 서비스와 사용자 서비스 간의 강한 결합을 만들어 독립적인 배포와 확장성을 저해합니다.

MSA 환경에서는 다음 방법을 고려해보세요:

  1. REST API 호출을 통한 서비스 간 통신
  2. 이벤트 기반 비동기 처리 (Event Sourcing)
  3. API Gateway를 통한 오케스트레이션

63-81: 트랜잭션 일관성 문제 지속

회원가입 메서드에서 userService.createUser()UserAuth 저장이 분리된 트랜잭션에서 실행될 가능성이 있습니다. 한쪽이 실패할 경우 데이터 불일치 상태가 발생할 수 있습니다.

🧹 Nitpick comments (3)
src/main/java/project/flipnote/user/entity/UserProfile.java (1)

17-18: 사용되지 않는 import 제거 필요

AccountRoleAccountStatus가 import되었지만 클래스 내에서 실제로 사용되지 않습니다. 리팩토링 과정에서 남은 불필요한 import로 보입니다.

-import project.flipnote.auth.entity.AccountRole;
-import project.flipnote.auth.entity.AccountStatus;
src/main/java/project/flipnote/auth/repository/UserAuthRepository.java (1)

30-32: 토큰 버전 증가 연산의 원자성을 보장해야 합니다.

incrementTokenVersion 메서드가 동시성 환경에서 안전한지 확인이 필요합니다. JPA의 @Modifying 쿼리가 원자적으로 실행되지만, 여러 스레드에서 동시에 호출될 경우를 고려해야 합니다.

더 안전한 구현을 위해 낙관적 잠금이나 @Version 컬럼 사용을 고려할 수 있습니다:

@Modifying
@Query("UPDATE UserAuth aa SET aa.tokenVersion = aa.tokenVersion + 1 WHERE aa.userId = :userId AND aa.tokenVersion = :currentVersion")
int incrementTokenVersionWithOptimisticLock(@Param("userId") Long userId, @Param("currentVersion") Long currentVersion);
src/main/java/project/flipnote/auth/entity/UserAuth.java (1)

69-71: 동시성 환경에서의 토큰 버전 증가 처리를 고려해야 합니다.

엔티티 레벨에서의 increaseTokenVersion() 메서드는 동시성 문제가 발생할 수 있습니다. Repository의 @Modifying 쿼리를 사용하는 것이 더 안전합니다.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 904c970 and a965e12.

📒 Files selected for processing (28)
  • src/main/java/project/flipnote/auth/controller/AuthController.java (3 hunks)
  • src/main/java/project/flipnote/auth/controller/OAuthController.java (2 hunks)
  • src/main/java/project/flipnote/auth/entity/AccountStatus.java (1 hunks)
  • src/main/java/project/flipnote/auth/entity/OAuthLink.java (3 hunks)
  • src/main/java/project/flipnote/auth/entity/UserAuth.java (1 hunks)
  • src/main/java/project/flipnote/auth/listener/UserWithdrawnEventListener.java (1 hunks)
  • src/main/java/project/flipnote/auth/model/UserRegisterRequest.java (2 hunks)
  • src/main/java/project/flipnote/auth/repository/OAuthLinkRepository.java (1 hunks)
  • src/main/java/project/flipnote/auth/repository/SocialLinkTokenRedisRepository.java (1 hunks)
  • src/main/java/project/flipnote/auth/repository/TokenVersionRedisRepository.java (1 hunks)
  • src/main/java/project/flipnote/auth/repository/UserAuthRepository.java (1 hunks)
  • src/main/java/project/flipnote/auth/service/AuthService.java (6 hunks)
  • src/main/java/project/flipnote/auth/service/OAuthService.java (4 hunks)
  • src/main/java/project/flipnote/auth/service/TokenVersionService.java (1 hunks)
  • src/main/java/project/flipnote/common/dto/UserCreateCommand.java (1 hunks)
  • src/main/java/project/flipnote/common/security/dto/AuthPrinciple.java (1 hunks)
  • src/main/java/project/flipnote/common/security/filter/JwtAuthenticationFilter.java (3 hunks)
  • src/main/java/project/flipnote/common/security/jwt/JwtComponent.java (3 hunks)
  • src/main/java/project/flipnote/common/security/jwt/JwtConstants.java (1 hunks)
  • src/main/java/project/flipnote/group/controller/GroupController.java (2 hunks)
  • src/main/java/project/flipnote/group/service/GroupService.java (4 hunks)
  • src/main/java/project/flipnote/user/controller/UserController.java (3 hunks)
  • src/main/java/project/flipnote/user/entity/UserProfile.java (3 hunks)
  • src/main/java/project/flipnote/user/entity/UserStatus.java (1 hunks)
  • src/main/java/project/flipnote/user/repository/UserProfileRepository.java (1 hunks)
  • src/main/java/project/flipnote/user/service/UserService.java (2 hunks)
  • src/test/java/project/flipnote/fixture/UserFixture.java (0 hunks)
  • src/test/java/project/flipnote/user/service/UserServiceTest.java (0 hunks)
💤 Files with no reviewable changes (2)
  • src/test/java/project/flipnote/fixture/UserFixture.java
  • src/test/java/project/flipnote/user/service/UserServiceTest.java
✅ Files skipped from review due to trivial changes (2)
  • src/main/java/project/flipnote/common/security/jwt/JwtConstants.java
  • src/main/java/project/flipnote/user/repository/UserProfileRepository.java
🚧 Files skipped from review as they are similar to previous changes (17)
  • src/main/java/project/flipnote/user/entity/UserStatus.java
  • src/main/java/project/flipnote/common/dto/UserCreateCommand.java
  • src/main/java/project/flipnote/group/controller/GroupController.java
  • src/main/java/project/flipnote/auth/model/UserRegisterRequest.java
  • src/main/java/project/flipnote/auth/entity/OAuthLink.java
  • src/main/java/project/flipnote/common/security/filter/JwtAuthenticationFilter.java
  • src/main/java/project/flipnote/auth/service/TokenVersionService.java
  • src/main/java/project/flipnote/auth/repository/OAuthLinkRepository.java
  • src/main/java/project/flipnote/auth/repository/SocialLinkTokenRedisRepository.java
  • src/main/java/project/flipnote/auth/service/OAuthService.java
  • src/main/java/project/flipnote/auth/controller/OAuthController.java
  • src/main/java/project/flipnote/group/service/GroupService.java
  • src/main/java/project/flipnote/auth/repository/TokenVersionRedisRepository.java
  • src/main/java/project/flipnote/common/security/jwt/JwtComponent.java
  • src/main/java/project/flipnote/auth/controller/AuthController.java
  • src/main/java/project/flipnote/user/controller/UserController.java
  • src/main/java/project/flipnote/user/service/UserService.java
🔇 Additional comments (17)
src/main/java/project/flipnote/user/entity/UserProfile.java (5)

24-26: 도메인 분리가 잘 반영된 명명

테이블명과 클래스명이 사용자 프로필 데이터에 집중하도록 명확하게 변경되었습니다. MSA 전환을 위한 도메인 분리 원칙에 잘 부합합니다.


54-69: 생성자가 프로필 도메인에 잘 집중됨

인증 관련 파라미터들이 제거되고 사용자 프로필 정보에만 집중하도록 잘 리팩토링되었습니다. 기본 상태를 ACTIVE로 설정하는 것도 적절합니다.


71-76: 업데이트 메서드가 프로필 도메인에 적절히 제한됨

프로필 관련 필드들만 업데이트하도록 잘 구성되어 있어 도메인 분리 원칙에 부합합니다.


49-51: UserStatus enum import 불필요 확인됨

UserStatus enum이 동일 패키지(project.flipnote.user.entity)에 정의되어 있어 import 없이도 참조 가능하며,
@Enumerated(EnumType.STRING) 애노테이션 적용도 적절합니다.


78-82: WITHDRAWN 상수 정의 확인 완료 및 탈퇴 메서드 승인

소프트 삭제 로직과 withdraw 명명 모두 적절하며, UserStatus enum에 WITHDRAWN 상수가 정의되어 있어 올바르게 사용되고 있습니다.

src/main/java/project/flipnote/auth/entity/AccountStatus.java (1)

1-8: 깔끔한 enum 구현입니다.

계정 상태를 나타내는 간단하고 명확한 enum으로, MSA 전환에 적합한 도메인 모델링이 잘 되어 있습니다.

src/main/java/project/flipnote/auth/repository/UserAuthRepository.java (1)

21-23: 비밀번호 암호화 처리 확인됨: updatePassword 호출 시 인코딩된 비밀번호 전달

  • AuthService.java (라인 151) 에서
    String encodedPassword = passwordEncoder.encode(req.password());
    이후 userAuthRepository.updatePassword(email, encodedPassword); 호출
  • 그 외에도 Service 레이어 전반에서 passwordEncoder.encode(...)를 사용하여 암호화된 비밀번호만 전달

따라서 Repository 레벨에서 별도의 암호화 검증 로직은 필요하지 않습니다.

src/main/java/project/flipnote/auth/entity/UserAuth.java (2)

47-59: Builder 패턴 구현이 우수합니다.

기본값 설정과 필수 필드만 받는 생성자 설계가 깔끔하며, MSA 환경에서 일관된 초기 상태를 보장합니다.


61-67: withdraw 메서드의 원자성을 개선해야 합니다.

현재 구현에서 softDelete()와 상태 변경, increaseTokenVersion() 호출이 분리되어 있어 일부만 성공할 위험이 있습니다.

메서드를 더 원자적으로 만들기 위해 다음과 같이 개선할 수 있습니다:

 public void withdraw() {
+    // 모든 상태 변경을 한 번에 수행
+    this.status = AccountStatus.WITHDRAWN;
+    this.tokenVersion++;
     super.softDelete();
-    
-    this.status = AccountStatus.WITHDRAWN;
-    
-    increaseTokenVersion();
 }

Likely an incorrect or invalid review comment.

src/main/java/project/flipnote/common/security/dto/AuthPrinciple.java (2)

13-23: Record 구조와 Spring Security 통합이 우수합니다.

인증 주체 정보를 담은 불변 레코드로서 깔끔하게 설계되었고, Spring Security와의 통합도 적절합니다.


25-29: UserAuth 엔티티로부터의 변환이 안전합니다.

null 체크는 JPA 엔티티의 제약 조건에 의해 보장되므로 현재 구현이 적절합니다.

src/main/java/project/flipnote/auth/service/AuthService.java (6)

84-88: 인증 엔티티 분리에 따른 적절한 수정

UserAuth 엔티티를 사용하도록 로그인 로직이 올바르게 수정되었습니다. 인증 데이터와 사용자 프로필 데이터의 분리가 명확해졌습니다.


123-125: 보안 DTO 도입으로 인한 적절한 수정

토큰에서 AuthPrinciple DTO를 추출하도록 변경된 것은 보안 계층의 추상화를 개선합니다. 토큰 처리 로직이 더 명확해졌습니다.


157-166: 보안을 고려한 우수한 비밀번호 변경 구현

현재 비밀번호 검증, 새 비밀번호 암호화, 토큰 버전 증가까지 포함된 완전한 비밀번호 변경 로직입니다. 기존 토큰 무효화를 통한 보안 강화가 잘 구현되었습니다.


168-181: 소셜 링크 관리 기능의 올바른 구현

소셜 링크 조회 및 삭제 기능이 적절한 권한 검증과 함께 구현되었습니다. 특히 deleteSocialLink에서 소유권 검증을 통해 보안이 강화되었습니다.


195-209: 헬퍼 메서드들의 일관된 리팩토링

UserAuth 엔티티와 AccountStatus를 사용하도록 헬퍼 메서드들이 일관되게 수정되었습니다. 활성 계정 상태 확인 로직이 명확해졌습니다.


152-152: 비밀번호 재설정 로직의 적절한 수정

UserAuthRepository를 사용하도록 비밀번호 업데이트 로직이 올바르게 수정되었습니다.

Comment on lines +31 to +41
public static AuthPrinciple from(Claims claims) {
long authId = Long.parseLong(claims.getId());
long userId = claims.get(JwtConstants.USER_ID, Long.class);
AccountRole userRole = AccountRole.from(
claims.get(JwtConstants.ROLE, String.class)
);
String email = claims.getSubject();
long tokenVersion = claims.get(JwtConstants.TOKEN_VERSION, Long.class);

return new AuthPrinciple(authId, userId, email, userRole, tokenVersion);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

JWT Claims 파싱 시 예외 처리를 강화해야 합니다.

Long.parseLong()claims.get() 호출에서 예외가 발생할 수 있지만 처리되지 않고 있습니다.

다음과 같이 안전한 파싱을 구현하는 것을 권장합니다:

 public static AuthPrinciple from(Claims claims) {
-    long authId = Long.parseLong(claims.getId());
-    long userId = claims.get(JwtConstants.USER_ID, Long.class);
-    AccountRole userRole = AccountRole.from(
-        claims.get(JwtConstants.ROLE, String.class)
-    );
-    String email = claims.getSubject();
-    long tokenVersion = claims.get(JwtConstants.TOKEN_VERSION, Long.class);
+    try {
+        long authId = Long.parseLong(claims.getId());
+        long userId = Optional.ofNullable(claims.get(JwtConstants.USER_ID, Long.class))
+            .orElseThrow(() -> new IllegalArgumentException("Missing USER_ID in claims"));
+        AccountRole userRole = AccountRole.from(
+            Optional.ofNullable(claims.get(JwtConstants.ROLE, String.class))
+                .orElseThrow(() -> new IllegalArgumentException("Missing ROLE in claims"))
+        );
+        String email = Optional.ofNullable(claims.getSubject())
+            .orElseThrow(() -> new IllegalArgumentException("Missing email in claims"));
+        long tokenVersion = Optional.ofNullable(claims.get(JwtConstants.TOKEN_VERSION, Long.class))
+            .orElseThrow(() -> new IllegalArgumentException("Missing TOKEN_VERSION in claims"));
 
-    return new AuthPrinciple(authId, userId, email, userRole, tokenVersion);
+        return new AuthPrinciple(authId, userId, email, userRole, tokenVersion);
+    } catch (NumberFormatException e) {
+        throw new IllegalArgumentException("Invalid authId format in JWT claims", e);
+    }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public static AuthPrinciple from(Claims claims) {
long authId = Long.parseLong(claims.getId());
long userId = claims.get(JwtConstants.USER_ID, Long.class);
AccountRole userRole = AccountRole.from(
claims.get(JwtConstants.ROLE, String.class)
);
String email = claims.getSubject();
long tokenVersion = claims.get(JwtConstants.TOKEN_VERSION, Long.class);
return new AuthPrinciple(authId, userId, email, userRole, tokenVersion);
}
public static AuthPrinciple from(Claims claims) {
try {
long authId = Long.parseLong(claims.getId());
long userId = Optional.ofNullable(claims.get(JwtConstants.USER_ID, Long.class))
.orElseThrow(() -> new IllegalArgumentException("Missing USER_ID in claims"));
AccountRole userRole = AccountRole.from(
Optional.ofNullable(claims.get(JwtConstants.ROLE, String.class))
.orElseThrow(() -> new IllegalArgumentException("Missing ROLE in claims"))
);
String email = Optional.ofNullable(claims.getSubject())
.orElseThrow(() -> new IllegalArgumentException("Missing email in claims"));
long tokenVersion = Optional.ofNullable(claims.get(JwtConstants.TOKEN_VERSION, Long.class))
.orElseThrow(() -> new IllegalArgumentException("Missing TOKEN_VERSION in claims"));
return new AuthPrinciple(authId, userId, email, userRole, tokenVersion);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid authId format in JWT claims", e);
}
}
🤖 Prompt for AI Agents
In src/main/java/project/flipnote/common/security/dto/AuthPrinciple.java lines
31 to 41, the method from(Claims claims) parses JWT claims without handling
potential exceptions from Long.parseLong() and claims.get() calls. To fix this,
wrap the parsing logic in try-catch blocks to catch and handle exceptions such
as NumberFormatException or ClassCastException, and provide fallback values or
throw a custom exception with a clear message to ensure robust and safe JWT
claims parsing.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/main/java/project/flipnote/auth/service/AuthService.java (1)

63-81: 회원가입 로직의 트랜잭션 일관성과 MSA 원칙 준수 필요

현재 구현에서 여전히 다음 문제들이 존재합니다:

  1. userService.createUser()UserAuth 저장이 분리된 트랜잭션에서 실행될 가능성
  2. 서비스 간 직접 호출로 인한 강한 결합

이는 이전 리뷰에서 지적된 동일한 문제들입니다.

🧹 Nitpick comments (1)
src/main/java/project/flipnote/auth/service/AuthService.java (1)

47-227: MSA 전환을 위한 리팩토링이 전반적으로 성공적으로 수행되었습니다.

인증 도메인이 User에서 UserAuth로 성공적으로 분리되었고, 트랜잭션 관리, 보안, 에러 처리 등이 일관성 있게 구현되어 있습니다. 새로운 기능들(회원가입, 비밀번호 변경, 소셜 링크 관리)도 적절히 추가되었습니다.

다만 UserService에 대한 직접 의존성은 여전히 서비스 간 결합도를 높이는 요소로 남아있어, 향후 완전한 MSA 전환 시 고려가 필요합니다.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a965e12 and feba2b1.

📒 Files selected for processing (10)
  • src/main/java/project/flipnote/auth/controller/AuthController.java (2 hunks)
  • src/main/java/project/flipnote/auth/controller/OAuthController.java (2 hunks)
  • src/main/java/project/flipnote/auth/controller/docs/AuthControllerDocs.java (1 hunks)
  • src/main/java/project/flipnote/auth/controller/docs/OAuthControllerDocs.java (1 hunks)
  • src/main/java/project/flipnote/auth/listener/UserWithdrawnEventListener.java (1 hunks)
  • src/main/java/project/flipnote/auth/repository/UserAuthRepository.java (1 hunks)
  • src/main/java/project/flipnote/auth/service/AuthService.java (6 hunks)
  • src/main/java/project/flipnote/common/config/SwaggerConfig.java (1 hunks)
  • src/main/java/project/flipnote/user/controller/UserController.java (2 hunks)
  • src/main/java/project/flipnote/user/controller/docs/UserControllerDocs.java (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • src/main/java/project/flipnote/user/controller/docs/UserControllerDocs.java
  • src/main/java/project/flipnote/auth/controller/docs/AuthControllerDocs.java
  • src/main/java/project/flipnote/auth/controller/docs/OAuthControllerDocs.java
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/main/java/project/flipnote/auth/listener/UserWithdrawnEventListener.java
  • src/main/java/project/flipnote/auth/repository/UserAuthRepository.java
  • src/main/java/project/flipnote/auth/controller/AuthController.java
  • src/main/java/project/flipnote/auth/controller/OAuthController.java
  • src/main/java/project/flipnote/user/controller/UserController.java
🔇 Additional comments (11)
src/main/java/project/flipnote/common/config/SwaggerConfig.java (2)

19-29: Bearer 토큰 기반 인증으로의 단순화가 MSA 전환에 적합합니다.

쿠키 기반 refresh-token에서 Bearer JWT 토큰 방식으로의 전환은 MSA 아키텍처에 매우 적합한 선택입니다. Stateless한 인증 방식은 서비스 간 통신과 확장성에 유리합니다.


29-29: 29번 라인 변경 검토 결과
닫는 괄호 이동만 표시된 것으로, 실제로는 refresh-token-cookie 관련 코드가 모두 삭제되었습니다.

주요 변경 사항:

  • SecurityRequirement에서 .addList("refresh-token-cookie") 제거
  • Components에서 addSecuritySchemes("refresh-token-cookie", …) 블록 전체 삭제

29번 라인의 변경 표시는 위 삭제에 따른 괄호 정렬 차이일 뿐이며, 실제 변경 내역은 위 두 부분입니다.

src/main/java/project/flipnote/auth/service/AuthService.java (9)

3-61: 임포트 및 의존성 주입이 적절하게 구성되었습니다.

MSA 전환을 위한 리팩토링에 필요한 새로운 엔티티와 레포지토리들이 올바르게 임포트되었고, 의존성 주입도 Spring 패턴을 따르고 있습니다.


83-89: 로그인 로직이 올바르게 리팩토링되었습니다.

UserAuth 엔티티를 사용하도록 업데이트되었고, 활성 계정 조회와 비밀번호 검증 로직이 적절하게 구현되어 있습니다.


91-102: 이메일 인증 코드 발송 로직이 적절하게 수정되었습니다.

회원가입 플로우에 맞게 이메일 중복 검증으로 변경된 것이 올바른 접근입니다.


115-126: 토큰 갱신 로직이 새로운 인증 모델에 맞게 적절히 업데이트되었습니다.

AuthPrinciple 사용으로 변경된 것이 일관성 있고 올바른 접근입니다.


128-155: 비밀번호 재설정 로직이 UserAuth 모델에 맞게 올바르게 업데이트되었습니다.

활성 계정 확인과 비밀번호 업데이트 로직이 새로운 아키텍처에 적절히 적응되었고, 보안 조치들이 잘 유지되고 있습니다.


157-166: 비밀번호 변경 메서드가 보안 모범 사례를 잘 따르고 있습니다.

현재 비밀번호 검증, 엔티티 메서드를 통한 비밀번호 업데이트, 토큰 버전 증가를 통한 기존 토큰 무효화까지 적절하게 구현되어 있습니다.


168-172: 소셜 링크 조회 메서드가 간결하고 올바르게 구현되었습니다.

레포지토리 패턴을 적절히 사용하고 있으며 로직이 명확합니다.


174-181: 소셜 링크 삭제 메서드가 보안을 고려하여 올바르게 구현되었습니다.

소유권 검증 후 삭제하는 로직이 적절하며, 사용자가 자신의 링크만 삭제할 수 있도록 보안이 잘 구현되어 있습니다.


183-226: 헬퍼 메서드들이 새로운 인증 모델에 맞게 적절히 업데이트되었습니다.

이메일 인증 확인, 활성 계정 조회, 이메일 중복 검증 등의 로직이 UserAuth 모델과 일관성 있게 구현되었고, 에러 처리 패턴도 통일되어 있습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants